--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Commit 6923c7e9b56a3961ee6bc88da3544dde76a31e6f
Parents : db2ad8a
Author : Mark Qvist <mark@unsigned.io>
Date : 2022-11-22T19:47:13+01:00
Added paper message sharing on Android
Changes
3 files changed, 162 insertions(+), 34 deletions(-)
Diff
diff --git a/sbapp/main.py b/sbapp/main.py
index 7ea2f8a8..32911840 100644
--- a/sbapp/main.py
+++ b/sbapp/main.py
@@ -1,4 +1,5 @@
-__debug_build__ = False
+# TODO: Reset
+__debug_build__ = True
__disable_shaders__ = True
__version__ = "0.4.0"
__variant__ = "beta"
@@ -271,6 +272,45 @@ class SidebandApp(MDApp):
mActivity.startActivity(shareIntent)
+ def share_image(self, image, filename):
+ if RNS.vendor.platformutils.get_platform() == "android":
+ save_path = self.sideband.exports_dir
+ file_path = save_path+"/"+filename
+
+ try:
+ if not os.path.isdir(save_path):
+ RNS.log("Creating directory: "+str(save_path))
+ os.makedirs(save_path)
+
+ Intent = autoclass("android.content.Intent")
+ Uri = autoclass("android.net.Uri")
+ File = autoclass("java.io.File")
+ FileProvider = autoclass("android.support.v4.content.FileProvider")
+
+ image.save(file_path)
+ i_file = File(file_path)
+ image_uri = FileProvider.getUriForFile(mActivity, "io.unsigned.sideband.provider", i_file)
+
+ shareIntent = Intent()
+ shareIntent.setAction(Intent.ACTION_SEND)
+ shareIntent.setType("image/png")
+ shareIntent.putExtra(Intent.EXTRA_STREAM, cast('android.os.Parcelable', image_uri))
+ mActivity.startActivity(shareIntent)
+
+ except Exception as e:
+ ok_button = MDRectangleFlatButton(text="OK",font_size=dp(18))
+ dialog = MDDialog(
+ title="Export Error",
+ text="The QR-code could not be exported and shared:\n\n"+str(e),
+ buttons=[ ok_button ],
+ )
+ def dl_ok(s):
+ dialog.dismiss()
+
+ ok_button.bind(on_release=dl_ok)
+ dialog.open()
+
+
def on_pause(self):
if self.sideband:
if self.sideband.getstate("flag.focusfix_pause"):
@@ -374,6 +414,52 @@ class SidebandApp(MDApp):
self.check_permissions()
+ def check_storage_permission(self):
+ storage_permissions_ok = False
+ if android_api_version < 30:
+ if check_permission("android.permission.WRITE_EXTERNAL_STORAGE"):
+ storage_permissions_ok = True
+ else:
+ self.request_storage_permission()
+
+ else:
+ Environment = autoclass('android.os.Environment')
+
+ if Environment.isExternalStorageManager():
+ storage_permissions_ok = True
+ else:
+ ok_button = MDRectangleFlatButton(text="OK",font_size=dp(18))
+ dialog = MDDialog(
+ title="Storage Permission",
+ text="Sideband needs permission to write to external storage to export, share and print paper messages.\n\nOn this Android version, the Manage All Files permission is needed, since normal external storage permission is no longer supported.\n\nSideband will only ever read and write to files in the \"Sideband\" folder of your external storage, and does not read any other data from your system.",
+ buttons=[ ok_button ],
+ )
+ def dl_ok(s):
+ dialog.dismiss()
+ self.request_storage_permission()
+
+ ok_button.bind(on_release=dl_ok)
+ dialog.open()
+
+ return storage_permissions_ok
+
+ def request_storage_permission(self):
+ if RNS.vendor.platformutils.get_platform() == "android":
+ if android_api_version < 30:
+ if not check_permission("android.permission.WRITE_EXTERNAL_STORAGE"):
+ RNS.log("Requesting storage write permission", RNS.LOG_DEBUG)
+ request_permissions(["android.permission.WRITE_EXTERNAL_STORAGE"])
+
+ if not check_permission("android.permission.READ_EXTERNAL_STORAGE"):
+ RNS.log("Requesting storage read permission", RNS.LOG_DEBUG)
+ request_permissions(["android.permission.READ_EXTERNAL_STORAGE"])
+ else:
+ Intent = autoclass('android.content.Intent')
+ Settings = autoclass('android.provider.Settings')
+ pIntent = Intent()
+ pIntent.setAction(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION)
+ mActivity.startActivity(pIntent)
+
def request_bluetooth_permissions(self):
if RNS.vendor.platformutils.get_platform() == "android":
if not check_permission("android.permission.BLUETOOTH_CONNECT"):
diff --git a/sbapp/sideband/core.py b/sbapp/sideband/core.py
index baf3d684..13157e7a 100644
--- a/sbapp/sideband/core.py
+++ b/sbapp/sideband/core.py
@@ -121,6 +121,7 @@ class SidebandCore():
self.db_path = self.app_dir+"/app_storage/sideband.db"
self.lxmf_storage = self.app_dir+"/app_storage/"
self.tmp_dir = self.app_dir+"/app_storage/tmp"
+ self.exports_dir = self.app_dir+"/exports"
self.first_run = True
@@ -135,6 +136,9 @@ class SidebandCore():
os.makedirs(self.tmp_dir)
else:
self.clear_tmp_dir()
+
+ if os.path.isdir(self.exports_dir):
+ self.clear_exports_dir()
except Exception as e:
RNS.log("Error while configuring Sideband: "+str(e), RNS.LOG_ERROR)
@@ -177,6 +181,13 @@ class SidebandCore():
fpath = self.tmp_dir+"/"+file
os.unlink(fpath)
+ def clear_exports_dir(self):
+ if os.path.isdir(self.exports_dir):
+ for file in os.listdir(self.exports_dir):
+ fpath = self.exports_dir+"/"+file
+ RNS.log("Clearing "+str(fpath))
+ os.unlink(fpath)
+
def __init_config(self):
RNS.log("Creating new Sideband configuration...")
if os.path.isfile(self.identity_path):
diff --git a/sbapp/ui/messages.py b/sbapp/ui/messages.py
index 310e7568..50f49855 100644
--- a/sbapp/ui/messages.py
+++ b/sbapp/ui/messages.py
@@ -220,6 +220,11 @@ class Messages():
def gen_save_qr(lxm, item):
if RNS.vendor.platformutils.is_android():
def x():
+ qr_image = lxm.as_qr()
+ hash_str = RNS.hexrep(lxm.hash[-2:], delimit=False)
+ filename = "Paper_Message_"+time.strftime(file_ts_format, time.localtime(m["sent"]))+"_"+hash_str+".png"
+ # filename = "Paper_Message.png"
+ self.app.share_image(qr_image, filename)
item.dmenu.dismiss()
return x
@@ -303,41 +308,67 @@ class Messages():
if m["method"] == LXMF.LXMessage.PAPER:
if RNS.vendor.platformutils.is_android():
qr_save_text = "Share QR Code"
+ dm_items = [
+ {
+ "viewclass": "OneLineListItem",
+ "text": "Share QR Code",
+ "height": dp(40),
+ "on_release": gen_save_qr(m["lxm"], item)
+ },
+ {
+ "viewclass": "OneLineListItem",
+ "text": "Copy LXM URI",
+ "height": dp(40),
+ "on_release": gen_copy_lxm_uri(m["lxm"], item)
+ },
+ {
+ "viewclass": "OneLineListItem",
+ "text": "Copy message text",
+ "height": dp(40),
+ "on_release": gen_copy(m["content"].decode("utf-8"), item)
+ },
+ {
+ "text": "Delete",
+ "viewclass": "OneLineListItem",
+ "height": dp(40),
+ "on_release": gen_del(m["hash"], item)
+ }
+ ]
+
else:
- qr_save_text = "Save QR Code"
+ dm_items = [
+ {
+ "viewclass": "OneLineListItem",
+ "text": "Print QR Code",
+ "height": dp(40),
+ "on_release": gen_print_qr(m["lxm"], item)
+ },
+ {
+ "viewclass": "OneLineListItem",
+ "text": "Save QR Code",
+ "height": dp(40),
+ "on_release": gen_save_qr(m["lxm"], item)
+ },
+ {
+ "viewclass": "OneLineListItem",
+ "text": "Copy LXM URI",
+ "height": dp(40),
+ "on_release": gen_copy_lxm_uri(m["lxm"], item)
+ },
+ {
+ "viewclass": "OneLineListItem",
+ "text": "Copy message text",
+ "height": dp(40),
+ "on_release": gen_copy(m["content"].decode("utf-8"), item)
+ },
+ {
+ "text": "Delete",
+ "viewclass": "OneLineListItem",
+ "height": dp(40),
+ "on_release": gen_del(m["hash"], item)
+ }
+ ]
- dm_items = [
- {
- "viewclass": "OneLineListItem",
- "text": "Print QR Code",
- "height": dp(40),
- "on_release": gen_print_qr(m["lxm"], item)
- },
- {
- "viewclass": "OneLineListItem",
- "text": qr_save_text,
- "height": dp(40),
- "on_release": gen_save_qr(m["lxm"], item)
- },
- {
- "viewclass": "OneLineListItem",
- "text": "Copy LXM URI",
- "height": dp(40),
- "on_release": gen_copy_lxm_uri(m["lxm"], item)
- },
- {
- "viewclass": "OneLineListItem",
- "text": "Copy message text",
- "height": dp(40),
- "on_release": gen_copy(m["content"].decode("utf-8"), item)
- },
- {
- "text": "Delete",
- "viewclass": "OneLineListItem",
- "height": dp(40),
- "on_release": gen_del(m["hash"], item)
- }
- ]
else:
dm_items = [
{
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────